﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using INSAForManagers.Models;

namespace INSAForManagers.Views
{
    
    public partial class FormAdditionSub : Form
    {
        /// <summary>
        /// 부모창 참조 객체
        /// </summary>
        private FormAddition parent;

        /// <summary>
        /// DataGridView와 연결할 DataTable
        /// </summary>
        private DataTable tbl;

        /// <summary>
        /// 창의 처음 높이
        /// </summary>
        private int windowOriginHeight;

        /// <summary>
        /// 창의 현재 높이
        /// </summary>
        private int windowHeight;

        /// <summary>
        /// 창 높이 조정 기본값
        /// </summary>
        private const int PANELHEIGHT = 35;

        public FormAdditionSub(FormAddition parent, DataTable tbl)
        {
            InitializeComponent();

            Control.CheckForIllegalCrossThreadCalls = false;

            this.parent = parent;
            this.tbl = parent.tbl;
        }

        private void FormAdditionSub_Load(object sender, EventArgs e)
        {
            try
            {
                initGroupList();

                windowOriginHeight = this.Height;
                windowHeight = this.Height;

                dtpWorkStart.Value = DateTime.Parse("2000-01-01");
                dtpWorkEnd.Value = DateTime.Parse("2000-01-01");
                dtpTargetStart.Value = DateTime.Parse("2000-01-01");
                dtpTargetEnd.Value = DateTime.Parse("2000-01-01");

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace, "확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 구분 목록을 초기화한다.
        /// </summary>
        private void initGroupList()
        {
            cboGroup.Items.Clear();

            ArrayList list = DBUtil.getAddGroupList();
            foreach (Hashtable hash in list)
            {
                AddGroup addGroup = new AddGroup();
                addGroup.Name = (string)hash["NAME"];
                addGroup.Code = (string)hash["CODE"];
                addGroup.RefCode = (string)hash["REF_CODE"];

                cboGroup.Items.Add(addGroup);
            }
        }

        private void cboGroup_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                AddGroup addGroup = (AddGroup)cboGroup.SelectedItem;
                setItemList(addGroup.Code);

                resetForm();

                if (addGroup.Code.Equals("A03"))//연수
                {
                    if (panWorkStart.Visible == false)
                    {
                        panWorkStart.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panWorkEnd.Visible == false)
                    {
                        panWorkEnd.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panTargetStart.Visible == true)
                    {
                        panTargetStart.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panTargetEnd.Visible == true)
                    {
                        panTargetEnd.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panDayCount.Visible == true)
                    {
                        panDayCount.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panMonthCount.Visible == false)
                    {
                        panMonthCount.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panDailyPoint.Visible == true)
                    {
                        panDailyPoint.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panMonthlyPoint.Visible == false)
                    {
                        panMonthlyPoint.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    lblContent.Text = "연수명";
                    txtContent.Text = "직무연수실적";
                    txtContent.ReadOnly = false;
                    lblOrgan.Text = "연수기관";
                    lblWorkStart.Text = "연수시작";
                    lblWorkEnd.Text = "연수마침";
                    lblMonthCount.Text = "연수시간";
                    lblMonthlyPoint.Text = "1학점당평정점";
                    txtMonthCount.ReadOnly = false;
                }
                else if (addGroup.Code.Equals("B08"))//자격증
                {
                    if (panWorkStart.Visible == true)
                    {
                        panWorkStart.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panWorkEnd.Visible == true)
                    {
                        panWorkEnd.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panTargetStart.Visible == true)
                    {
                        panTargetStart.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panTargetEnd.Visible == false)
                    {
                        panTargetEnd.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panDayCount.Visible == true)
                    {
                        panDayCount.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panMonthCount.Visible == true)
                    {
                        panMonthCount.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panDailyPoint.Visible == true)
                    {
                        panDailyPoint.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }

                    if (panMonthlyPoint.Visible == true)
                    {
                        panMonthlyPoint.Visible = false;
                        resetWindowHeight(EResizeWindow.UP);
                    }
                    
                    lblContent.Text = "내용";
                    txtContent.Text = "";
                    txtContent.ReadOnly = false;
                    lblOrgan.Text = "시행기관";
                    lblTargetEnd.Text = "자격취득일";
                }
                else//나머지
                {
                    if (panWorkStart.Visible == false)
                    {
                        panWorkStart.Visible = true;                        
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panWorkEnd.Visible == false)
                    {
                        panWorkEnd.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panTargetStart.Visible == false)
                    {
                        panTargetStart.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panTargetEnd.Visible == false)
                    {
                        panTargetEnd.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panDayCount.Visible == false)
                    {
                        panDayCount.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panMonthCount.Visible == false)
                    {
                        panMonthCount.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panDailyPoint.Visible == false)
                    {
                        panDailyPoint.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    if (panMonthlyPoint.Visible == false)
                    {
                        panMonthlyPoint.Visible = true;
                        resetWindowHeight(EResizeWindow.DOWN);
                    }

                    lblContent.Text = "내용";
                    txtContent.Text = "";
                    txtContent.ReadOnly = false;
                    lblOrgan.Text = "근무기관";
                    lblWorkStart.Text = "근무시작";
                    lblWorkEnd.Text = "근무마침";
                    lblTargetEnd.Text = "대상마침";
                    lblMonthCount.Text = "평정월수";
                    lblMonthlyPoint.Text = "월평정점";
                    txtMonthCount.ReadOnly = true;
                }

                this.Height = windowHeight;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace, "확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 창 높이를 조정한다.
        /// </summary>
        /// <param name="direction">방향</param>
        private void resetWindowHeight(EResizeWindow direction)
        {
            if (direction == EResizeWindow.UP)
            {
                windowHeight -= PANELHEIGHT;
            }
            else
            {
                windowHeight += PANELHEIGHT;
            }

            if (windowOriginHeight <= windowHeight)
            {
                windowHeight = windowOriginHeight;
                return;
            }
                
            this.Height = windowHeight;
            
        }

        /// <summary>
        /// 폼을 리셋
        /// </summary>
        private void resetForm()
        {
            txtContent.Text = "";
            txtOrgan.Text = "";
            dtpWorkStart.Value = DateTime.Now;
            dtpWorkEnd.Value = DateTime.Now;
            dtpTargetStart.Value = DateTime.Now;
            dtpTargetEnd.Value = DateTime.Now;
            txtMonthCount.Text = "0";
            txtDayCount.Text = "0";
            txtMonthlyPoint.Text = "0.0";
            txtDailyPoint.Text = "0.0";
            txtAddPoint.Text = "0.0";
        }

        /// <summary>
        /// 항목 목록을 갱신한다.
        /// </summary>
        /// <param name="group_code">구분(그룹 코드)</param>
        private void setItemList(string group_code)
        {
            cboItem.Items.Clear();

            ArrayList list = DBUtil.getAddItemList(group_code);           

            foreach (Hashtable hash in list)
            {
                AdditionItem additionitem = new AdditionItem();
                additionitem.Type = (EAddType)hash["TYPE"];
                additionitem.GroupCode = (string)hash["GROUPS"];
                additionitem.ItemCode = (string)hash["ITEM"];
                additionitem.Name = (string)hash["NAME"];
                additionitem.Donator = (string)hash["DONATOR"];
                additionitem.MonthlyPoint = (double)hash["MONTHLYPOINT"];
                additionitem.DailyPoint = (double)hash["DAILYPOINT"];
                additionitem.TrainningTime = (int)hash["TRAINNINGTIME"];
                additionitem.PointPerTime = (double)hash["POINTPERTIME"];
                additionitem.MaxPerYear = (double)hash["MAXPERYEAR"];
                additionitem.MaxPoint = (double)hash["MAXPOINT"];
                additionitem.ApplyStartDate = (DateTime)hash["APPLYSTARTDATE"];
                additionitem.ApplyEndDate = (DateTime)hash["APPLYENDDATE"];

                cboItem.Items.Add(additionitem);

            }

        }

        private void lnkCalc_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                calcEvaluePoint((AddGroup)cboGroup.SelectedItem, (AdditionItem)cboItem.SelectedItem);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 연수/자격증/나머지 에 대해 평정점을 계산한다.
        /// </summary>
        /// <param name="objGroup">그룹</param>
        /// <param name="objItem">항목</param>
        private void calcEvaluePoint(AddGroup objGroup, AdditionItem objItem)
        {
            if (objGroup == null || objItem == null)
            {
                throw new Exception("그룹 및 항목을 선택하세요!    ");
            }

            if (objGroup.Code.Equals("A03"))//연수
            {
                calEvalueTrainningPoint(objGroup, objItem);
            }
            else if (objGroup.Code.Equals("B08"))//자격증
            {
                calEvalueLicensePoint(objGroup, objItem);
            }
            else//경력
            {
                calcEvalueTheOtherPoint(objGroup, objItem);
            }
        }

        /// <summary>
        /// 경력가산점을 계산한다.
        /// </summary>
        /// <param name="objGroup">그룹</param>
        /// <param name="objItem">항목</param>
        private void calcEvalueTheOtherPoint(AddGroup objGroup, AdditionItem objItem)
        {
            if (dtpWorkStart.Value.CompareTo(dtpWorkEnd.Value) >= 0 || dtpTargetStart.Value.CompareTo(dtpTargetEnd.Value) >= 0)
            {
                MessageBox.Show("시작 날짜는 마침날짜와 같거나 이후일 수 없습니다.  ", "확인", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            int[] tmp = Util.getMonthCount(dtpTargetStart.Value, dtpTargetEnd.Value);
            txtMonthCount.Text = tmp[0].ToString();
            txtDayCount.Text = tmp[1].ToString();

            txtMonthlyPoint.Text = objItem.MonthlyPoint.ToString("0.0000");
            txtDailyPoint.Text = objItem.DailyPoint.ToString("0.00000");

            double addPoint = tmp[0] * objItem.MonthlyPoint + tmp[1] * objItem.DailyPoint;

            txtAddPoint.Text = addPoint.ToString("0.00000");
        }

        /// <summary>
        /// 자격증관련 가산점을 계산한다.
        /// </summary>
        /// <param name="objGroup">그룹</param>
        /// <param name="objItem">항목</param>
        private void calEvalueLicensePoint(AddGroup objGroup, AdditionItem objItem)
        {
            
        }

        /// <summary>
        /// 연수관련 가산점을 계산한다.
        /// </summary>
        /// <param name="objGroup">그룹</param>
        /// <param name="objItem">항목</param>
        private void calEvalueTrainningPoint(AddGroup objGroup, AdditionItem objItem)
        {
            int trainningTime = Int32.Parse(txtMonthCount.Text);
            int score = trainningTime / objItem.TrainningTime;

            txtMonthlyPoint.Text = objItem.PointPerTime.ToString("0.0000");
            txtAddPoint.Text = ((double)score * objItem.PointPerTime).ToString("0.0000");

        }

        private void cboItem_SelectedIndexChanged(object sender, EventArgs e)
        {
            AddGroup addGroup = (AddGroup)cboGroup.SelectedItem;
            AdditionItem addItem = (AdditionItem)cboItem.SelectedItem;

            if(addGroup.Code.Equals("B08"))
            {
                txtAddPoint.Text = addItem.MaxPoint.ToString("0.0000");
            }
        }

        private void btnApply_Click(object sender, EventArgs e)
        {
            try
            {

                //이미 등록한 같은 그룹의 다른 요소들을 검색하여 합산 혹은 중복 적용할 수 없는 경우는 교체(평정점이 더 높을 경우)

                //선택된 항목
                AdditionItem addItem = (AdditionItem)cboItem.SelectedItem;

                //현재 선택 그룹과 중복 여부
                AddGroup addGroup = (AddGroup)cboGroup.SelectedItem;

                string ref_code = addGroup.RefCode;

                /*
                 * 경력가산점
                 * */
                if (!addGroup.Code.Equals("A03") && !addGroup.Code.Equals("B08"))
                {
                    //평정점
                    double evaluePoint = Double.Parse(txtAddPoint.Text);

                    //대상시작일자
                    DateTime targetStartDate = dtpTargetStart.Value;

                    //대상마침일자
                    DateTime targetEndDate = dtpTargetEnd.Value;                    

                                        
                    double totalPoint = getTotalAddPointByGroup(addGroup.Code);

                    //최대값 확인
                    if (totalPoint >= addItem.MaxPoint) throw new Exception("이미 해당 항목의 최대점수를 초과하였습니다.   ");

                    //대용/협력학교
                    if (addGroup.Code.Equals("B11"))
                    {
                        if (Double.Parse(txtAddPoint.Text) > 0.04)
                        {
                            txtAddPoint.Text = "0.04";
                        }
                    }

                    //적용 날짜 확인
                    if (!addItem.ApplyStartDate.ToShortDateString().Equals("1900-01-01"))
                    {
                        if (addItem.ApplyStartDate.Date.CompareTo(targetStartDate.Date) > 0) throw new Exception("적용 날짜가 적절한지 확인하세요.   ");
                    }
                    if (!addItem.ApplyEndDate.ToShortDateString().Equals("1900-01-01"))
                    {
                        if (addItem.ApplyEndDate.Date.CompareTo(targetEndDate.Date) < 0) throw new Exception("적용 날짜가 적절한지 확인하세요.   ");
                    }

                    //입력된 경력가산점과 기간이 중복되는 지 확인
                    for (int i = 0; i < tbl.Rows.Count; i++)
                    {
                        if (((string)tbl.Rows[i][12]).Equals("A03") || ((string)tbl.Rows[i][12]).Equals("B08")) continue;
                        string sd = ((string)tbl.Rows[i][5]).Substring(0, 10);
                        string ed = ((string)tbl.Rows[i][6]).Substring(0, 10);

                        if ((targetStartDate.ToShortDateString().CompareTo(sd) >= 0 && targetEndDate.ToShortDateString().CompareTo(ed) <= 0) ||
                            (sd.CompareTo(targetStartDate.ToShortDateString()) >= 0 && ed.CompareTo(targetEndDate.ToShortDateString()) <= 0))
                        {
                            //ref_code와 각 행의 그룹코드를 비교해서 중복 가능하면 skip함
                            if (ref_code.IndexOf((string)tbl.Rows[i][12]) >= 0 || addGroup.Code.Equals((string)tbl.Rows[i][12]))
                            {
                                MessageBox.Show("중복된 기간의 가산점 항목이 존재합니다.  \n\n확인하세요.\n\n");
                                return;
                            }
                        }
                    }


                    if ((totalPoint + Double.Parse(txtAddPoint.Text)) > addItem.MaxPoint)
                    {
                        double tmp = addItem.MaxPoint - totalPoint;
                        txtAddPoint.Text = tmp.ToString("0.00000");
                    }

                    ArrayList data = new ArrayList();
                    data.Add(parent.pcode);
                    data.Add(addGroup.Code);
                    data.Add(addItem.ItemCode);
                    data.Add(txtContent.Text);
                    data.Add(txtOrgan.Text);
                    data.Add(dtpWorkStart.Value.ToShortDateString());
                    data.Add(dtpWorkEnd.Value.ToShortDateString());
                    data.Add(dtpTargetStart.Value.ToShortDateString());
                    data.Add(dtpTargetEnd.Value.ToShortDateString());
                    data.Add(Int32.Parse(txtMonthCount.Text));
                    data.Add(Int32.Parse(txtDayCount.Text));
                    data.Add(Double.Parse(txtMonthlyPoint.Text));
                    data.Add(Double.Parse(txtDailyPoint.Text));
                    data.Add(Double.Parse(txtAddPoint.Text));
                    data.Add(DateTime.Now);
                    data.Add(DBUtil.addNextOrder(parent.pcode));

                    DBUtil.insertAdditionInfo(data);  
                    
                   
                }
                //연수가산점
                else if (addGroup.Code.Equals("A03"))
                {
                    string thisYear = dtpWorkStart.Value.Date.ToShortDateString().Substring(0, 4);

                    double pointPerYear = getTotalPointByYear("A03", thisYear);

                    if (pointPerYear == addItem.MaxPerYear)
                    {
                        MessageBox.Show("이미 연평정점에 도달하였으므로 해당 항목을 반영할 수 없습니다.  ", "확인", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }

                    if (pointPerYear + Double.Parse(txtAddPoint.Text) > addItem.MaxPerYear)
                    {
                        MessageBox.Show("연평정점을 초과하게 되므로 평정점의 일부분만 반영합니다.  ", "확인", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        txtAddPoint.Text = (addItem.MaxPerYear - pointPerYear).ToString("0.0000");
                    } 

                    double totalPoint = getTotalAddPointByGroup("A03");
                    if (addItem.MaxPoint < totalPoint) throw new Exception("이미 해당 항목의 최대점수를 초과하였습니다.   ");
                    
                    if ((totalPoint + Double.Parse(txtAddPoint.Text)) > addItem.MaxPoint)
                    {
                        double tmp = addItem.MaxPoint - totalPoint;
                        txtAddPoint.Text = tmp.ToString("0.0000");
                    }

                    ArrayList data = new ArrayList();
                    data.Add(parent.pcode);
                    data.Add(addGroup.Code);
                    data.Add(addItem.ItemCode);
                    data.Add(txtContent.Text);
                    data.Add(txtOrgan.Text);
                    data.Add("");
                    data.Add("");
                    data.Add(dtpWorkStart.Value.ToShortDateString());
                    data.Add(dtpWorkEnd.Value.ToShortDateString());
                    data.Add(Int32.Parse(txtMonthCount.Text));
                    data.Add(0);
                    data.Add(Double.Parse(txtMonthlyPoint.Text));
                    data.Add(0.0);
                    data.Add(Double.Parse(txtAddPoint.Text));
                    data.Add(DateTime.Now);
                    data.Add(DBUtil.addNextOrder(parent.pcode));

                    DBUtil.insertAdditionInfo(data); 

                }
                //국가기술자격증
                else if (addGroup.Code.Equals("B08"))
                {
                    double totalPoint = getTotalAddPointByGroup("B08");

                    if (addItem.MaxPoint < totalPoint) throw new Exception("이미 해당 항목의 최대점수를 초과하였습니다.   ");

                    if ((totalPoint + Double.Parse(txtAddPoint.Text)) > addItem.MaxPoint)
                    {
                        double tmp = addItem.MaxPoint - totalPoint;
                        txtAddPoint.Text = tmp.ToString("0.0000");
                    }

                    ArrayList data = new ArrayList();
                    data.Add(parent.pcode);
                    data.Add(addGroup.Code);
                    data.Add(addItem.ItemCode);
                    data.Add(txtContent.Text);
                    data.Add(txtOrgan.Text);
                    data.Add("");
                    data.Add("");
                    data.Add(dtpTargetEnd.Value.ToShortDateString());
                    data.Add("");
                    data.Add(0);
                    data.Add(0);
                    data.Add(0.0);
                    data.Add(0.0);
                    data.Add(Double.Parse(txtAddPoint.Text));
                    data.Add(DateTime.Now);
                    data.Add(DBUtil.addNextOrder(parent.pcode));

                    DBUtil.insertAdditionInfo(data); 
                }

                //가산점 데이터그리드 갱신
                parent.initGrid();

                //가산점 항목이 추가되었으므로 새로 계산을 필요로 함
                parent.calcRequired = true;
                parent.applyRequired = true;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace, "확인", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 그룹코드로 가산점 그리드의 평정점 합계를 계산한다.
        /// </summary>
        /// <param name="groupCode">그룹코드</param>
        /// <returns>평정점 합계</returns>
        private double getTotalAddPointByGroup(string groupCode)
        {
            int cntRow = tbl.Rows.Count;
            double totalPoint = 0.0;

            for (int i = 0; i < cntRow; i++)
            {
                if (((string)tbl.Rows[i][12]).Equals(groupCode))
                {
                    totalPoint += (double)tbl.Rows[i][11];
                }
            }
            return totalPoint;
        }

        private double getTotalPointByYear(string groupCode, string prevYear)
        {
            int cntRow = tbl.Rows.Count;
            double totalPoint = 0.0;
            string thisYear = "";

            for (int i = 0; i < cntRow; i++)
            {
                if (((string)tbl.Rows[i][12]).Equals(groupCode))
                {
                    //해당 그룹의 항목의 연도 확인
                    thisYear = tbl.Rows[i][5].ToString().Substring(0, 4);

                    //이전 항목의 연도와 현재 항목의 연도가 같으면 평정점을 누계함
                    if (prevYear.Equals(thisYear))
                    {
                        totalPoint += (double)tbl.Rows[i][11];
                    }

                }
            }

            return totalPoint;
        }
    }
}
